import {GenCode} from "./../expressExt/GenCode";
import * as fs from "fs";
import {GenCfg} from "./GenCfg";
import {exp, expType} from "../expressExt/exp";
import {Meta} from "../expressExt/public/Meta";
import {sdf, arrayString} from "../expressExt/public/sdf";
import {sql} from "../expressExt/db/Isql";
import {ObjectID} from "mongodb";

export class HtmlCode {

    static indexFile = "index.html";
    static menu = ()=> GenCfg.codeOutMenu + "/html/";
    static urlList = arrayString();


    /**
     * index.html内容
     * @returns {string}
     */
    static genIndex() {
        let ret = `<html>
        <meta charset="utf-8">
                <head>
                    <title>接口说明</title>
                </head>
                <body>
                <ul>
                `;

        for (let url of HtmlCode.urlList) {
            //接口注释
            let apiComment = GenCode.readComment(GenCfg.expFuncStr, url, GenCfg.ExpressExtCommentPos);
            ret += `<li>${apiComment}:<a href="${GenCode.fixUrl(url)}.html">${url}</a></li>`
        }

        ret += `
        </ul>
            </body>
            </html>`;
        return ret;
    }

    /**
     * 生成html文档说明
     * @param url
     * @param modReq 接口入参
     * @param resp 接口返回对象
     * @param isPost
     */
    static genFile(url: string, modReq: { new(): any;}, resp: any, isPost: "false"|"true") {
        //文档目录
        let menu = HtmlCode.menu();
        if (!fs.existsSync(menu))
            fs.mkdirSync(menu);

        //目录文件
        let indexFileReal = menu + HtmlCode.indexFile;
        if (fs.existsSync(indexFileReal))
            return;

        if (url == null) {//收尾
            fs.writeFileSync(indexFileReal, HtmlCode.genIndex());
        }
        else {
            HtmlCode.urlList.push(url);
            //接口详细说明文件
            let fileName = GenCode.fixUrl(url) + ".html";
            let file = menu + fileName;
            //接口注释
            let apiComment = GenCode.readComment(GenCfg.expFuncStr, url, GenCfg.ExpressExtCommentPos);

            //生成接口详细说明文件
            if (!fs.existsSync(file)) {
                console.error(file);
                fs.writeFileSync(file, HtmlCode.genHtml(url, modReq, resp, isPost, apiComment));
            }
        }
    }

    /**
     * 生成接口详细说明文件
     * @param url
     * @param modReq
     * @param resp
     * @param isPost
     * @param apiComment
     */
    static genHtml(url: string, modReq: { new(): any;}, resp: any, isPost: "false"|"true", apiComment: string) {

        let ret = "<html><meta charset=\"utf-8\">" +
            "<head>" +
            "    <title>" + apiComment + "</title>" +
            "</head><body>";

        ret += "<h2>" + apiComment + "</h2>"
        ret += "<h3>" + url + "</h3>"


        if (isPost == "true") {
            ret += "<p>类型:post</p>"
        }
        else {
            ret += "<p>类型:get</p>"
        }
        let noValid = exp.getNoValid(modReq);
        if (!noValid) {
            // ret += "<p><b>需要传uid,token登录验证</b></p>"
        }

        ret += "<b>接口传入参数:</b><br>";

        let req = new modReq();
        for (let key in req) {
            let val = req[key];
            if (val instanceof exp) {
                if (Meta.getArrayType(modReq, key)) {
                    val = [];
                }
                else if ((val as exp).type == expType.int || (val as exp).type == expType.number) {
                    val = 1;
                } else if ((val as exp).type == expType.file) {

                }
                else {
                    val = "";
                }
            }
            if (val instanceof ObjectID) {
                val = "";
            }

            ret += HtmlCode.recurObj(val, key, modReq, "&nbsp;");

            // if (typeof req[key] === "number") {
            //     ret += "(数字)";
            // }
            // else {
            //     ret += "(字串)";
            // }
            // ret += GenCode.readComment(modReq.toString(), "this." + key, 1);
            // ret += "</div>";
        }

        ret += "<br><hr><b>接口返回数据:</b><br>";

        ret += HtmlCode.recurObj(resp, "", resp.constructor, "")

        ret += "<br><b>返回示例:</b><br>";

        ret += "<pre>" + JSON.stringify(resp) + "<pre/>";

        ret += "</body></html>";

        return ret;
    }


    /**
     * 解析嵌套对象
     * @param resp
     * @returns {string}
     */
    static recurObj(resp: any, name: string, classType: any, tabSize: string) {
        let ret = "";

        let thisName = "";
        if (name.length > 0)
            thisName += "this." + name;

        let type = typeof resp;


        if (type == "number" || resp instanceof Number) {
            ret += tabSize + "<b>" + name + "</b>:(数字)" + GenCode.readComment(classType, thisName, 1) + "<br>";
        }
        else if (type == "string" || (type == "object" && resp == null) || resp instanceof String) {


            ret += tabSize + "<b>" + name + "</b>:(字串)" + GenCode.readComment(classType, thisName, 1) + "<br>";
        }
        else if (resp instanceof exp) {
            ret += tabSize + "<b>" + name + "</b>:(文件)" + GenCode.readComment(classType, thisName, 1) + "<br>";
        }
        else if (resp instanceof Array) {
            ret += tabSize + "<b>" + name + "</b>:(数组)" + GenCode.readComment(classType, thisName, 1) + "[" + "<br>";
            //数组有内容
            if ((resp as Array<any>).length > 0) {
                let arrObj = (resp as  Array<any>)[0] as any;
                let clasType = classType;
                if (arrObj && arrObj.constructor.name !== "Object") {
                    // ret += "arrObj.constructor:" + arrObj.constructor.name;
                    clasType = arrObj.constructor;
                }
                ret += HtmlCode.recurObj(arrObj, "", clasType, "&nbsp;&nbsp;" + tabSize);
            }
            else { //数组无内容从sdf.arrayType取类型
                let arrType = Meta.getArrayType(classType, name);
                if (!arrType)
                    arrType = sdf.getArrayType(resp);

                if (arrType) {
                    ret += HtmlCode.recurObj(new arrType(), "", arrType, "&nbsp;&nbsp;" + tabSize);
                }
            }
            ret += tabSize + "]" + "<br>";
        }

        else if (type == "object") {

            // if (classType.name !== "Object") {
            ret += tabSize + "<b>" + name + "</b>:(嵌套)" + GenCode.readComment(classType, thisName, 1) + "{" + "<br>";
            // }

            for (let key in resp) {
                let clasType = classType;
                let val = resp[key];
                let type = typeof val;
                if (val && type != "string" && type != "number" && val.constructor.name !== "Object" && !(val instanceof Array)) {
                    // ret += "val.constructor.name:" + val.constructor.name;
                    clasType = val.constructor;
                }
                if (val instanceof ObjectID) {
                    val = "";
                }

                ret += HtmlCode.recurObj(val, key, clasType, "&nbsp;&nbsp;" + tabSize);
            }

            if (classType != null) {
                ret += tabSize + "}" + "<br>";
            }

        }

        return ret;
    }
}